/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/5/29 19:19
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.aurora.core.container.bootstrap;

import com.hyacinth.aurora.core.container.initializer.AuroraChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;

import static com.hyacinth.aurora.constant.Constant.SystemProperties.APPLICATION_THREAD_BOOS_NAME;
import static com.hyacinth.aurora.constant.Constant.SystemProperties.APPLICATION_THREAD_WORK_NAME;


/**
 * netty服务端启动程序
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class NettyBootStrap extends AuroraBootstrap {

    private EventLoopGroup bossGroup = new NioEventLoopGroup(1,new DefaultThreadFactory(APPLICATION_THREAD_BOOS_NAME));
    private EventLoopGroup workGroup = new NioEventLoopGroup(0,new DefaultThreadFactory(APPLICATION_THREAD_WORK_NAME));

    private Channel channel;

    @Override
    protected void doStart() throws Exception {
        ServerBootstrap bootstrap = new ServerBootstrap()
                .group(bossGroup, workGroup)
                // 设置相关属性
                // 系统用于临时存放已完成三次握手的请求的队列的最大长度，
                // 如果连接建立频繁，服务器处理创建新连接较慢，可以适当调大这个参数
                .option(ChannelOption.SO_BACKLOG, 2048)
                // 表示是否开启TCP底层心跳机制，true为开启
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                // 是否开启Nagle算法，true表示关闭，false表示开启，
                // 通俗地说，如果要求高实时性，有数据发送时就马上发送，就关闭，
                // 如果需要减少发送次数减少网络交互，就开启
                .childOption(ChannelOption.TCP_NODELAY, false)
                .channel(NioServerSocketChannel.class)
                .childHandler(new AuroraChannelInitializer());

        // 线程同步阻塞等待服务器绑定到指定端口
        ChannelFuture future = bootstrap.bind(appConfig.getPort()).sync();
        // 获取通道
        channel = future.channel();
    }

    @Override
    protected void joinServer() {
        addCloseChannelListener();
    }

    /**
     * 添加同步管道关闭监听器
     */
    private void addCloseChannelListener() {
        /*
         * 成功绑定到端口之后,给channel增加一个管道关闭的监听器并同步阻塞,
         * 直到channel关闭,线程才会往下执行,结束进程。
         */
        try {
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            LOGGER.error("添加同步管道关闭监听失败", e);
        }
    }

    @Override
    protected void release() {
        bossGroup.shutdownGracefully();
        workGroup.shutdownGracefully();
    }
}
